home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_Tix.idb / usr / freeware / lib / tix4.1 / fs.tcl.z / fs.tcl
Encoding:
Text File  |  1999-01-26  |  10.8 KB  |  626 lines

  1. # tixAssert --
  2. #
  3. #    Debugging routine. Evaluates the test script in the context of the
  4. #    caller. The test script is responsible for generating the error.
  5. #    
  6. proc tixAssert {script} {
  7.     uplevel $script
  8. }
  9.  
  10. proc tixAssertNorm {path} {
  11.     if ![tixFSIsNorm $path] {
  12.     error "\"$path\" is not a normalized path"
  13.     }
  14. }
  15.  
  16. proc tixAssertVPath {vpath} {
  17.     if ![tixFSIsVPath $vpath] {
  18.     error "\"$vpath\" is not a VPATH"
  19.     }
  20. }
  21.  
  22. # tixFSAbsPath --
  23. #
  24. #    Converts $path into an normalized absolute path
  25. #
  26. proc tixFSAbsPath {path} {
  27.     return [lindex [tixFSNorm [tixFSVPWD] $path] 0]
  28. }
  29.  
  30. # tixFSVPWD --
  31. #
  32. #    Returns the VPATH of the current directory.
  33. #
  34. proc tixFSVPWD {} {
  35.     return [tixFSVPath [tixFSPWD]]
  36. }
  37.  
  38. if {![info exists tcl_platform] || $tcl_platform(platform) == "unix"} {
  39.  
  40. # tixFSPWD --
  41. #
  42. #    Return the current directory
  43. #
  44. proc tixFSPWD {} {
  45.     return [pwd]
  46. }
  47.  
  48. # tixFSDisplayName --
  49. #
  50. #    Returns the name of a normalized path which is usually displayed by
  51. #    the OS
  52. #
  53. proc tixFSDisplayName {normpath} {
  54.     tixAssert {
  55.     tixAssertNorm $normpath
  56.     }
  57.     return $normpath
  58. }
  59.  
  60. proc tixFSIsAbsPath {path} {
  61.     return [tixStrEq [string index $path 0] /]
  62. }
  63.  
  64. # tixFSIsNorm_os --
  65. #
  66. #    Returns true iff this pathname is normalized, in the OS native name
  67. #    format
  68. #
  69. proc tixFSIsNorm_os {path} {
  70.     return [tixFSIsNorm $path]
  71. }
  72.  
  73. proc tixFSIsNorm {path} {
  74.     if [tixStrEq $path /] {
  75.     return 1
  76.     }
  77.  
  78.     # relative path
  79.     #
  80.     if ![regexp {^/} $path] {
  81.     return 0
  82.     }
  83.  
  84.     if [regexp {/[.]$} $path] {
  85.     return 0
  86.     }
  87.     if [regexp {/[.][.]$} $path] {
  88.     return 0
  89.     }
  90.     if [regexp {/[.]/} $path] {
  91.     return 0
  92.     }
  93.     if [regexp {/[.][.]/} $path] {
  94.     return 0
  95.     }
  96.     if [tixStrEq $path .] {
  97.     return 0
  98.     }
  99.     if [tixStrEq $path ..] {
  100.     return 0
  101.     }
  102.  
  103.     # Tilde
  104.     #
  105.     if [regexp {^~} $path] {
  106.     return 0
  107.     }
  108.  
  109.     # Double slashes
  110.     #
  111.     if [regexp {//} $path] {
  112.     return 0
  113.     }
  114.  
  115.     # Trailing slashes
  116.     #
  117.     if [regexp {/$} $path] {
  118.     return 0
  119.     }
  120.  
  121.     return 1
  122. }
  123.  
  124. # tixFSIsValid --
  125. #
  126. #    Checks whether a native pathname contains invalid characters.
  127. #
  128. proc tixFSIsValid {path} {
  129.     return 1
  130. }
  131.  
  132. proc tixFSIsVPath {vpath} {
  133.     return [tixFSIsNorm $vpath]
  134. }
  135.  
  136. # tixFSVPath --
  137. #
  138. #    Converts a native pathname to its VPATH
  139. #
  140. proc tixFSVPath {path} {
  141.     tixAssert {
  142.     tixAssertNorm $path
  143.     }
  144.     return $path
  145. }
  146.  
  147. # tixFSPath --
  148. #
  149. #    Converts a vpath to a native pathname
  150. proc tixFSPath {vpath} {
  151.     tixAssert {
  152.     tixAssertVPath $vpath
  153.     }
  154.     return $vpath
  155. }
  156.  
  157. # tixFSTildeSubst -- [Unix only]
  158. #
  159. #    Substitutes any leading tilde characters if possible. No error is
  160. #    generated if the user doesn't exist.
  161. #
  162. proc tixFSTildeSubst {text} {
  163.     if [tixStrEq [string index $text 0] ~] {
  164.     # The following will report if the user doesn't exist
  165.     if [catch {
  166.         file isdir $text
  167.     }] {
  168.         return ./$text
  169.     }
  170.     return [tixFile tilde $text]
  171.     } else {
  172.     return $text
  173.     }
  174. }
  175.  
  176. # tixFSNorm --
  177. #
  178. #    Interprets the user's input and return file information about this
  179. #    input.
  180. #
  181. # Arguments:
  182. #    See documentation (docs/Files.txt)
  183. #
  184. proc tixFSNorm {context text {defFile ""} {flagsVar ""} {errorMsgVar ""}} {
  185.     tixAssert {
  186.     tixAssertVPath $context
  187.     }
  188.  
  189.     if ![tixStrEq $errorMsgVar ""] {
  190.     upvar $errorMsgVar errorMsg
  191.     }
  192.     if ![tixStrEq $flagsVar ""] {
  193.     upvar $flagsVar flags
  194.     }
  195.  
  196.     set hasDirSuffix [regexp {/$} $text]
  197.     set text [tixFSTildeSubst $text]
  198.     set text [_tixJoin $context $text]
  199.  
  200.     if {$hasDirSuffix || [file isdir $text]} {
  201.     set dir $text
  202.     set tail $defFile
  203.     } else {
  204.     set dir [file dirname $text]
  205.     set tail [file tail $text]
  206.     }
  207.  
  208.     set norm $dir/$tail
  209.     regsub -all /+ $norm / norm
  210.     if ![tixStrEq $norm /] {
  211.     regsub {/$} $norm "" norm
  212.     }
  213.  
  214.     if ![info exists flag(noPattern)] {
  215.     set isPat 0
  216.     foreach char [split $tail ""] {
  217.         if {$char == "*" || $char == "?"} {
  218.         set isPat 1
  219.         break
  220.         }
  221.     }
  222.     if {$isPat} {
  223.         return [list $norm $dir "" $tail]
  224.     }
  225.     }
  226.  
  227.     return [list $norm $dir $tail ""]
  228. }
  229.  
  230. # _tixJoin -- [Internal]
  231. #    Joins two native pathnames.
  232. #
  233. proc _tixJoin {p1 p2} {
  234.     if [tixStrEq [string index $p2 0] /] {
  235.     return [_tixNormalize $p2]
  236.     } else {
  237.     return [_tixNormalize $p1/$p2]
  238.     }
  239. }
  240.  
  241. # tixFSNormDir --
  242. #
  243. #    Normalizes an absolute path.
  244. #
  245. proc tixFSNormDir {dir} {
  246.     set dir [tixFile tilde $dir]
  247.     if ![tixStrEq [string index $dir 0] /] {
  248.     error "\"$dir\" must be an absolute pathname"
  249.     }
  250.     if ![file isdir $dir] {
  251.     error "\"$dir\" is not a directory"
  252.     }
  253.     return [_tixNormalize $dir]
  254. }
  255.  
  256. # _tixNormalize --
  257. #
  258. #    Normalizes an absolute pathname.
  259. #
  260. #     $dir must be an absolute pathname
  261. #
  262. proc _tixNormalize {path} {
  263.     tixAssert {
  264.     if ![tixStrEq [string index $path 0] /] {
  265.         error "\"$path\" must be an absolute pathname"
  266.     }
  267.     }
  268.  
  269.     # Don't be fooled: $path doesn't need to be a directory. The following
  270.     # code just makes it easy to get rid of trailing . and ..
  271.     #
  272.     set path $path/
  273.     regsub -all /+ $path / path
  274.     while 1 {
  275.     if ![regsub {/\./} $path "/" path] break
  276.     }
  277.     while 1 {
  278.     if ![regsub {/\.$} $path "" path] break
  279.     }
  280.  
  281.     while 1 {
  282.     if ![regsub {/[^/]+/\.\./} $path "/" path] break
  283.     while 1 {
  284.         if ![regsub {^/\.\./} $path "/" path] break
  285.     }
  286.     }
  287.     while 1 {
  288.     if ![regsub {^/\.\./} $path "/" path] break
  289.     }
  290.  
  291.     regsub {/$} $path "" path
  292.     if [tixStrEq $path ""] {
  293.     return /
  294.     } else {
  295.     return $path
  296.     }
  297. }
  298.  
  299. # tixFSCreateDirs
  300. #
  301. #
  302. proc tixFSCreateDirs {path} {
  303.     tixAssert {
  304.     error "Procedure tixFSCreateDirs not implemented on all platforms"
  305.     }
  306.     if [tixStrEq $path /] {
  307.     return 1
  308.     }
  309.     if [file exists $path] {
  310.     return 1
  311.     }
  312.     if ![tixFSCreateDirs [file dirname $path]] {
  313.     return 0
  314.     }
  315.     if [catch {exec mkdir $path}] {
  316.     return 0
  317.     }
  318.     return 1
  319. }
  320.  
  321. } else {
  322.  
  323. #-Win--------------------------------------------------------------------
  324.  
  325. # (Win) tixFSPWD --
  326. #
  327. #    Return the current directory
  328. #
  329. proc tixFSPWD {} {
  330.     set p [pwd]
  331.     regsub -all / $p \\ p
  332.     return $p
  333. }
  334. # Win
  335. #
  336. proc tixFSIsNorm {path} {
  337.  
  338.     # Drive root directory
  339.     #
  340.     if [regexp {^[A-z]:$} $path] {
  341.     return 1
  342.     }
  343.  
  344.     # If it is not a drive root directory, it must
  345.     # have a leading [drive letter:]\\[non empty string]
  346.     if ![regexp {^[A-z]:\\.} $path] {
  347.     return 0
  348.     }
  349.  
  350.     # relative path
  351.     #
  352.     if [regexp {\\[.]$} $path] {
  353.     return 0
  354.     }
  355.     if [regexp {\\[.][.]$} $path] {
  356.     return 0
  357.     }
  358.     if [regexp {\\[.]\\} $path] {
  359.     return 0
  360.     }
  361.     if [regexp {\\[.][.]\\} $path] {
  362.     return 0
  363.     }
  364.     if [tixStrEq $path .] {
  365.     return 0
  366.     }
  367.     if [tixStrEq $path ..] {
  368.     return 0
  369.     }
  370.  
  371.     # Double slashes
  372.     #
  373.     if [regexp {\\\\} $path] {
  374.     return 0
  375.     }
  376.  
  377.     # Trailing slashes
  378.     #
  379.     if [regexp {[\\]$} $path] {
  380.     return 0
  381.     }
  382.  
  383.     return 1
  384. }
  385.  
  386. # (Win) tixFSNorm --
  387. #
  388. #    Interprets the user's input and return file information about this
  389. #    input.
  390. #
  391. # Arguments:
  392. #    See documentation (docs/Files.txt)
  393. #
  394. proc tixFSNorm {context text {defFile ""} {flagsVar ""} {errorMsgVar ""}} {
  395.     tixAssert {
  396.     tixAssertVPath $context
  397.     }
  398.  
  399.     if ![tixStrEq $errorMsgVar ""] {
  400.     upvar $errorMsgVar errorMsg
  401.     }
  402.     if ![tixStrEq $flagsVar ""] {
  403.     upvar $flagsVar flags
  404.     }
  405.  
  406.     set isDir [regexp {[\\]$} $text]
  407.     set text [_tixJoin $context $text]
  408.     set path [tixFSPath $text]
  409.  
  410.     if {$isDir || [file isdir $path]} {
  411.     set vpath $text
  412.     set tail $defFile
  413.     } else {
  414.     set list [split $text \\]
  415.     set tail [lindex $list end]
  416.     set len [string length $tail]
  417.     set vpath [string range $text 0 [expr [string len $text]-$len-1]]
  418.     regsub {[\\]$} $vpath "" vpath
  419.     }
  420.  
  421.     set path [tixFSPath $vpath]
  422.  
  423.     if ![info exists flag(noPattern)] {
  424.     set isPat 0
  425.     foreach char [split $tail ""] {
  426.         if {$char == "*" || $char == "?"} {
  427.         set isPat 1
  428.         break
  429.         }
  430.     }
  431.     if {$isPat} {
  432.         return [list $path $vpath "" $tail]
  433.     }
  434.     }
  435.  
  436.     return [list $path $vpath $tail ""]
  437. }
  438.  
  439. # Win
  440. #
  441. # _tixJoin -- [internal]
  442. #
  443. #    Joins a pathname to a VPATH
  444. #
  445. proc _tixJoin {vp1 p2} {
  446.     if [tixFSIsAbsPath $p2] {
  447.     return [tixFSVPath [_tixNormalize $p2]]
  448.     } else {
  449.     return [tixFSVPath [_tixNormalize [tixFSPath $vp1]\\$p2]]
  450.     }
  451. }
  452.  
  453. # (Win) tixFSIsAbsPath
  454. #
  455. #    The Tcl "file pathtype" is buggy. E.g. C:\.\..\. is absolute, but
  456. #    "file pathtype" thinks that it isn't
  457. #
  458.  
  459. proc tixFSIsAbsPath {path} {
  460.     return [regexp {^[A-z]:\\} $path]
  461. }
  462.  
  463. # (Win) tixFSIsNorm_os
  464. #
  465. #    Returns true iff this pathname is normalized, in the OS native name
  466. #    format
  467. #
  468. proc tixFSIsNorm_os {path} {
  469.     if [regexp {^[A-z]:[\\]$} $path] {
  470.     return 1
  471.     }
  472.     if [regexp {^[A-z]:$} $path] {
  473.     return 0
  474.     }
  475.  
  476.     return [tixFSIsNorm $path]
  477.  
  478. }
  479.  
  480. # Win
  481. #
  482. # _tixNormalize --
  483. #
  484. #    Normalizes an absolute pathname.
  485. #
  486. #     $dir must be an absolute native pathname
  487. #
  488. proc _tixNormalize {abpath} {
  489.     tixAssert {
  490.     if ![tixFSIsAbsPath $abpath] {
  491.         error "\"$abpath\" must be an absolute pathname"
  492.     }
  493.     }
  494.  
  495.     if ![regexp {^[A-z]:} $abpath drive] {
  496.     tixPanic "\"$abpath\" does not contain a drive letter"
  497.     }
  498.     set drive [string toupper $drive]
  499.  
  500.     regsub {^[A-z]:} $abpath "" path
  501.  
  502.     # Don't be fooled: $path doesn't need to be a directory. The following
  503.     # code "set path $path\\" just makes it easy to get rid of trailing
  504.     # . and ..
  505.     #
  506.     set path $path\\
  507.     regsub -all {[\\]+} $path \\ path
  508.     while 1 {
  509.     if ![regsub {\\[.]\\} $path "\\" path] break
  510.     }
  511.     while 1 {
  512.     if ![regsub {\\[.]$} $path "" path] break
  513.     }
  514.  
  515.     while 1 {
  516.     if ![regsub {\\[^\\]+\\[.][.]\\} $path "\\" path] break
  517.     while 1 {
  518.         if ![regsub {^\\[.][.]\\} $path "\\" path] break
  519.     }
  520.     }
  521.     while 1 {
  522.     if ![regsub {^\\[.][.]\\} $path "\\" path] break
  523.     }
  524.  
  525.     regsub {[\\]+$} $path "" path
  526.     return $drive$path
  527. }
  528.  
  529. # Win
  530. #
  531. # tixFSNormDir --
  532. #
  533. #    Normalizes a directory
  534. #
  535. proc tixFSNormDir {dir} {
  536.     if ![tixFSIsAbsPath $dir] {
  537.     error "\"$dir\" must be an absolute pathname"
  538.     }
  539.     if ![file isdir $dir] {
  540.     error "\"$dir\" is not a directory"
  541.     }
  542.     return [_tixNormalize $dir]
  543. }
  544.  
  545.  
  546. proc tixPanic {message} {
  547.     error $message
  548. }
  549.  
  550. # tixFSIsValid --
  551. #
  552. #    Checks whether a native pathname contains invalid characters.
  553. #
  554. proc tixFSIsValid {path} {
  555.     return 1
  556. }
  557.  
  558. # Win
  559. #
  560. #
  561. proc tixFSIsVPath {vpath} {
  562.     global tixPriv
  563.     if $tixPriv(isWin95) {
  564.     return [string match {xx\\xx\\[A-z]:*} $vpath]
  565.     } else {
  566.     return [string match {xx\\[A-z]:*} $vpath]
  567.     }
  568. }
  569.  
  570. # Win
  571. #
  572. # tixFSVPath --
  573. #
  574. #    Converts a normalized native pathname to its VPATH
  575. #
  576. proc tixFSVPath {path} {
  577.     global tixPriv
  578.  
  579.     tixAssert {
  580.     tixAssertNorm $path
  581.     }
  582.     return $tixPriv(WinPrefix)\\$path
  583. }
  584.  
  585. # tixFSPath --
  586. #
  587. #    Converts a vpath to a native pathname
  588. proc tixFSPath {vpath} {
  589.     global tixPriv
  590.     tixAssert {
  591.     tixAssertVPath $vpath
  592.     }
  593.     if $tixPriv(isWin95) {
  594.     set path [string range $vpath 6 end]
  595.     } else {
  596.     set path [string range $vpath 3 end]
  597.     }
  598.     regsub {:$} $path :\\ path
  599.  
  600.     return $path
  601. }
  602.  
  603. # tixFSDisplayName --
  604. #
  605. #    Returns the name of a normalized path which is usually displayed by
  606. #    the OS
  607. #
  608. proc tixFSDisplayName {normpath} {
  609.     tixAssert {
  610.     tixAssertNorm $normpath
  611.     }
  612.  
  613.     if [regexp {^[A-z]:$} $normpath] {
  614.     return $normpath\\
  615.     } else {
  616.     return $normpath
  617.     }
  618. }
  619.  
  620.  
  621. tixInitFileCmpt:Win 
  622.  
  623. }
  624.